//
// Created by Administrator on 2025/8/18.
//

#include "data_codec.h"

#include "cJSON.h"
#include "printf_rtos.h"
#include "sqlist.h"
#include "sensor_manager.h"
#include "lwip/sockets.h"
#include "modbusrtu_task.h"
#include "event_groups.h"
#include "malloc_ex.h"
#include "freertos_demo.h"
#define  MAX_SENSOR_COUNT       255
#define  INTERVAL_S_SEND        10
#define STATIC_JSON_BUF_SIZE    4096
extern float internal_temp_celsius;
extern SeqList_t g_sensor_registry;
extern EventGroupHandle_t g_init_eventgroup;
uint16_t sensor_count=2;
char *sensor_id[]={
    "m_temp","m_led"};
char *sensor_data[MAX_SENSOR_COUNT];
static char *json_buffer=NULL; // 使用静态预分配的缓冲区来生成JSON字符串，避免动态分配内存失败
SemaphoreHandle_t sensor_data_mutex=NULL;
QueueHandle_t sensor_recv_queue=NULL;
QueueHandle_t sensor_send_queue=NULL;
BaseType_t process_property_set_command(const char *payload)
{
    if (payload == NULL) {
        return pdFAIL;
    }

    cJSON *root = cJSON_Parse(payload);
    if (root == NULL)
    {
        printf_rtos("Failed to parse JSON\n");
        return pdFAIL;
    }

    // 验证 method
    cJSON *method = cJSON_GetObjectItem(root, "method");
    if (!method || !cJSON_IsString(method) || strcmp(method->valuestring, "thing.service.property.set") != 0)
    {
        printf_rtos("Not a property set method\n");
        cJSON_Delete(root);
        return pdFAIL;
    }

    // 获取 params 对象
    cJSON *params = cJSON_GetObjectItem(root, "params");
    if (params == NULL || !cJSON_IsObject(params))
    {
        printf_rtos("Params object not found or not an object\n");
        cJSON_Delete(root);
        return pdFAIL;
    }

    cJSON *current_param = NULL;
    cJSON_ArrayForEach(current_param, params)
    {
        const char *l_sensor_id = current_param->string;

        // 在栈上创建一个 sensor_config_t 实例，用于接收查找结果
        sensor_config_t sensor;

        // 使用安全的函数来查找传感器
        if (find_sensor_by_id_and_copy(l_sensor_id, &sensor) == pdPASS)
        {
            // 检查传感器是否可写
            if ((sensor.direction == SENSOR_DIR_INPUT || sensor.direction == SENSOR_DIR_INOUT) &&
                 sensor.write_func != NULL)
            {
                sensor_value_t new_value;
                bool value_parsed = false;

                // 根据传感器配置的类型，来解析收到的值
                switch (sensor.type)
                {
                    // ... case 语句块保持不变, 但使用 sensor.type, 而不是 sensor->type ...
                    case SENSOR_DATA_TYPE_INT:
                        if (cJSON_IsNumber(current_param)) {
                            new_value.val_int = current_param->valueint;
                            value_parsed = true;
                        }
                        break;
                    case SENSOR_DATA_TYPE_FLOAT:

                        break;
                }

                // 如果值解析成功，就调用写函数指针
                if (value_parsed) {
                    printf_rtos("Setting property '%s'\n", l_sensor_id);
                    // 注意：现在 sensor 是一个结构体实例，所以使用 . 而不是 ->
                    sensor.write_func(sensor.slave_addr,sensor.start_addr, new_value);
                } else {
                    printf_rtos("Value type mismatch for sensor '%s'\n", l_sensor_id);
                }
            }
        }
        else
        {
            // 应该打印当前正在处理的 l_sensor_id。
            printf_rtos("Sensor '%s' not found or not writable.\n", l_sensor_id);
        }
    }

    cJSON_Delete(root);
    return pdPASS;
}

// void data_codec_init(void *pvParams)
// {
//     UNUSED(pvParams);
//     xEventGroupWaitBits(g_init_eventgroup,BIT_MQTT_READY,pdFALSE,pdTRUE,portMAX_DELAY);
//     sensor_recv_queue = xQueueCreate(5, sizeof(sensor_raw_data_t));
//     sensor_send_queue = xQueueCreate(5, sizeof(char *));
//     if (json_buffer==NULL)
//         mymalloc(SRAMEX,sizeof(char)*STATIC_JSON_BUF_SIZE);
//     xEventGroupSetBits(g_init_eventgroup,BIT_CODEC_READY);
//     vTaskDelete(NULL);
// }

void sensor_decode(void *pvParams)
{
    UNUSED(pvParams);
    xEventGroupWaitBits(g_init_eventgroup,BIT_MQTT_READY,pdFALSE,pdTRUE,portMAX_DELAY);
    printf_rtos("sensor_decode task start\n");
    sensor_raw_data_t raw_data={.payload = NULL,0};
    xEventGroupSetBits(g_init_eventgroup,BIT_DECODEC_READY);
    for (;;)
    {
        if (xQueueReceive(sensor_recv_queue,&raw_data,portMAX_DELAY)==pdTRUE)
        {
            printf_rtos("sensor_decode task receive data\n");
            process_property_set_command(raw_data.payload);
            vPortFree(raw_data.payload);
            raw_data.payload=NULL;
        }
        size_t uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );
        printf_rtos("decode stack high water mark: %u words\n", uxHighWaterMark);
    }
}

void sensor_codec(void *pvParams)
{
    xEventGroupWaitBits(g_init_eventgroup,BIT_MQTT_READY,pdFALSE,pdTRUE,portMAX_DELAY);
    UNUSED(pvParams);
    printf_rtos("sensor_codec task start\n");
    sensor_recv_queue = xQueueCreate(5, sizeof(sensor_raw_data_t));
    sensor_send_queue = xQueueCreate(5, sizeof(char *));
    if (json_buffer==NULL)
        json_buffer=(char *)mymalloc(SRAMEX,sizeof(char)*STATIC_JSON_BUF_SIZE);
    sensor_data_mutex=xSemaphoreCreateMutex();
    xSemaphoreGive(sensor_data_mutex);
    sensor_registry_init();
    sensor_config_t aio_temp={
        .id = "m_temp",.name="aio_temp",.type = SENSOR_DATA_TYPE_INT,\
        .read_func = modbus_holding_regs_validate,.slave_addr = 0x01,.start_addr = 0x02,\
        .reg_num = 1,.decode_formula = FORMULA_AIO,.direction = SENSOR_DIR_OUTPUT,\
        .write_func = NULL,.unit = "C"
    };
    SeqList_PushBack(&g_sensor_registry,&aio_temp);
    sensor_config_t aio_humi={
        .id = "m_humi",.name="aio_humi",.type = SENSOR_DATA_TYPE_INT,\
        .read_func = modbus_holding_regs_validate,.slave_addr = 0x01,.start_addr = 0x03,\
        .reg_num = 1,.decode_formula = FORMULA_AIO,.direction = SENSOR_DIR_OUTPUT,\
        .write_func = NULL,.unit = "%RH"
    };
    SeqList_PushBack(&g_sensor_registry,&aio_humi);
    sensor_config_t aio_pm25={
        .id = "m_pm25",.name="aio_pm25",.type = SENSOR_DATA_TYPE_INT,\
        .read_func = modbus_holding_regs_validate,.slave_addr = 0x01,.start_addr = 0x05,\
        .reg_num = 1,.decode_formula = FORMULA_AIO,.direction = SENSOR_DIR_OUTPUT,\
        .write_func = NULL,.unit = "ug/m3"
    };
    SeqList_PushBack(&g_sensor_registry,&aio_pm25);
    sensor_config_t aio_air={
        .id = "m_air",.name="aio_air",.type = SENSOR_DATA_TYPE_INT,\
        .read_func = modbus_holding_regs_validate,.slave_addr = 0x01,.start_addr = 0x01,\
        .reg_num = 1,.decode_formula = FORMULA_AIO,.direction = SENSOR_DIR_OUTPUT,\
        .write_func = NULL,.unit = "ppb"
    };
    sensor_config_t aio_air_pressure={
        .id = "m_pressure",.name="aio_air_pressure",.type = SENSOR_DATA_TYPE_FLOAT,\
        .read_func = modbus_holding_regs_validate,.slave_addr = 0x01,.start_addr = 0x06,\
        .reg_num = 1,.decode_formula = FORMULA_AIO_AIR_P,.direction = SENSOR_DIR_OUTPUT,\
        .write_func = NULL,.unit = "hpa"
    };
    SeqList_PushBack(&g_sensor_registry,&aio_air_pressure);

    SeqList_PushBack(&g_sensor_registry,&aio_air);
    sensor_config_t aio_human={
        .id = "m_human",.name="aio_human",.type = SENSOR_DATA_TYPE_INT,\
        .read_func = modbus_holding_regs_validate,.slave_addr = 0x01,.start_addr = 0x04,\
        .reg_num = 1,.decode_formula = FORMULA_AIO,.direction = SENSOR_DIR_OUTPUT,\
        .write_func = NULL,.unit = ""
    };
    SeqList_PushBack(&g_sensor_registry,&aio_human);
    xEventGroupSetBits(g_init_eventgroup,BIT_CODEC_READY);
    for (;;) 
    {
        cJSON *root=NULL;
        cJSON *params=NULL;
        root=cJSON_CreateObject();
        params=cJSON_CreateObject();
        if (root==NULL)
        {
            vTaskDelay(pdMS_TO_TICKS(INTERVAL_S_SEND*1000));
            continue;
        }
        xSemaphoreTake(sensor_data_mutex, portMAX_DELAY);
        for (size_t i = 0;i<g_sensor_registry.size;i++)
        {
            // sensor_config_t *sensor=pvPortMalloc(sizeof(sensor_config_t));
            // SeqList_Get(&g_sensor_registry,i,sensor);

            sensor_config_t *sensor=&((sensor_config_t *)g_sensor_registry.data)[i];
            if (sensor->name[0]!='\0'&&(sensor->direction==SENSOR_DIR_OUTPUT||sensor->direction==SENSOR_DIR_INOUT)&&sensor->read_func!=NULL)
            {
                if (sensor->read_func(sensor->slave_addr,sensor->start_addr,sensor->reg_num,sensor->decode_formula,&(sensor->data))==pdPASS)
                {
                    switch (sensor->type)
                    {
                        case SENSOR_DATA_TYPE_FLOAT:
                        {
                            char value_str[20];
                            int integer_part = (int)sensor->data.val_float;
                            int fractional_part = (int)((sensor->data.val_float - integer_part) * 100);
                            snprintf(value_str, sizeof(value_str), "%d.%02d", integer_part, fractional_part < 0 ? -fractional_part : fractional_part);
                            cJSON_AddRawToObject(params, sensor->id, value_str);
                            break;
                        }
                        case SENSOR_DATA_TYPE_INT:
                            cJSON_AddNumberToObject(params,sensor->id,sensor->data.val_int);
                            break;
                        case SENSOR_DATA_TYPE_STRING:
                            cJSON_AddStringToObject(params,sensor->id,sensor->data.val_string);
                            break;
                        case SENSOR_DATA_TYPE_ARRAY:
                            break;
                        case SENSOR_DATA_TYPE_TIME:
                            break;
                        default:
                            break;
                    }
                }
                // vTaskDelay(1000);
            }
        }
        xSemaphoreGive(sensor_data_mutex);
        cJSON_AddItemToObject(root,"params",params);
        if (!cJSON_PrintPreallocated(root, json_buffer, STATIC_JSON_BUF_SIZE, 0)) {
            printf_rtos("Error: JSON buffer too small!\n");
            cJSON_Delete(root);
            root = NULL;
            vTaskDelay(pdMS_TO_TICKS(INTERVAL_S_SEND * 1000));
            continue;
        }

        cJSON_Delete(root);
        root=NULL;

        // 注意：现在发送的是指向静态缓冲区的指针，接收方需要复制数据而不是释放它
        char *json_string_ptr = json_buffer;
        if (xQueueSend(sensor_send_queue, &json_string_ptr, 0) != pdPASS)
        {
            // 发送失败，无需释放json_string_ptr，因为它指向静态内存
            vTaskDelay(1000);
            continue;
        }
        size_t uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );
        printf_rtos("codec stack high water mark: %u words\n", uxHighWaterMark); // 假设你有log_debug
        vTaskDelay(pdMS_TO_TICKS(INTERVAL_S_SEND*1000));
    }







    // char m_temp[16];
    // char m_led[4];
    // for (;;) 
    // {
    //     sensor_interpreted_data interpreted_data={0};
    //     snprintf(m_temp,sizeof(m_temp),"%.2f",internal_temp_celsius);
    //     sensor_data[0]=m_temp;
    //     snprintf(m_led,sizeof(m_led),"%d",!HAL_GPIO_ReadPin(GPIOF,GPIO_PIN_10));
    //     sensor_data[1]=m_led;
    //     interpreted_data.sensor_count=sensor_count;
    //     interpreted_data.sensor_id=sensor_id;
    //     interpreted_data.sensor_data=sensor_data;
    //
    //     xQueueSend(sensor_send_queue,&interpreted_data,0);
    //     vTaskDelay(pdMS_TO_TICKS(INTERVAL_S_SEND*1000));
    // }
}